package v1

import (
	"GOPAAS/configs/config"
	"GOPAAS/internal/app/services"
	"GOPAAS/internal/utils"
	"encoding/json"
	"fmt"
	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"image"
	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"
	"os"
	"regexp"
	"strconv"
	"time"
)

// PostLogin 登录
func PostLogin(c *gin.Context) {
	loginType := c.DefaultPostForm("type", "0")                 //登陆类型：0：用帐号手机邮箱与密码登陆  1：手机验证码登陆 2.app扫码登录
	registration_id := c.DefaultPostForm("registration_id", "") //极光ID
	//login_info := getRequestInfo(c)
	var _user services.SignRes
	var err error
	var login string
	switch loginType {
	case "0": //用户名密码登陆
		login = c.PostForm("username")
		password := c.PostForm("password")
		if login == "" || password == "" {
			utils.Error(c, -1, "参数错误", nil)
			return
		}
		_user, err = services.UserLoginByPass(login, password, registration_id)
	case "1":
		//短信验证码登陆
		login = c.PostForm("login")
		code := c.PostForm("code")
		_user, err = services.UserLoginByCode(login, code, registration_id)
	case "2": //扫码登录
		token := c.PostForm("token")
		_user, err = services.UserLoginByToken(token)
	}
	UserService := services.GetUserService(_user.Uid)
	if err != nil {
		//UserService.AddLoginRecord(login_info.UserAgent, login_info.ModelNumber, login_info.IP, login, "异常", login_info.Bower, fmt.Sprintf("%s", err))
		utils.Error(c, -1, fmt.Sprintf("登录失败：%s", err), nil)
		return
	}
	//UserService.AddLoginRecord(login_info.UserAgent, login_info.ModelNumber, login_info.IP, login, "正常", login_info.Bower, fmt.Sprintf("%s", err))
	UserService.AddUserLog()
	login_type, _ := c.Get("login_type")
	if login_type == "web" {
		session := sessions.Default(c)
		session.Set("user_id", _user.Uid)
		session.Set("user_name", _user.Name)
		session.Set("user_avatar", _user.Image128)
		session.Set("company_id", _user.CompanyId)
		session.Set("access_token", _user.AccessToken)
		err = session.Save()
		if err != nil {
			utils.Error(c, -1, fmt.Sprintf("登录失败：%s", err), nil)
			return
		}
	}
	utils.Success(c, "登录成功", _user)
	return
}

// CheckLogin 手机确认登录
func CheckLogin(c *gin.Context) {
	key := c.PostForm("key")
	user_id, _ := c.Get("user_id")
	status_str := c.DefaultPostForm("status", "0")
	//user_id_int, err := strconv.Atoi(user_id_str)
	status, err := strconv.Atoi(status_str)
	if err != nil || key == "" {
		utils.Error(c, -1, "参数错误", nil)
		return
	}
	param := map[string]string{
		"uuid":            key,
		"uid":             "1",
		"partner_id":      "",
		"company_id":      "1",
		"name":            "",
		"follow":          "1",
		"type":            "orient",
		"database_secret": key,
	}
	body := utils.Res{
		Errcode: 0,
		Errmsg:  "ok",
		Data:    map[string]interface{}{"key": key, "status": status},
		Message: "success",
	}
	if status == 1 {
		err = services.AppCheckLogin(key, user_id.(int64))
		if err != nil {
			err_msg := fmt.Sprintf("登录失败：%s", err)
			body = utils.Res{
				Errcode: -1,
				Errmsg:  "no",
				Data:    map[string]interface{}{"key": key, "status": status},
				Message: err_msg,
			}
			message, _ := json.Marshal(body)
			utils.SendSocket(param, string(message))
			utils.Error(c, -1, err_msg, nil)
			return
		}
		message, _ := json.Marshal(body)
		utils.SendSocket(param, string(message))
		utils.Success(c, "登录成功", nil)
		return
	}
	//正在扫码
	message, _ := json.Marshal(body)
	utils.SendSocket(param, string(message))
	utils.Success(c, "发送成功", nil)
	return
}

// PostFastLogin 一键登录
func PostFastLogin(c *gin.Context) {
	login_token := c.PostForm("login_token")
	registration_id := c.DefaultPostForm("registration_id", "") //极光ID

	client_type := c.DefaultPostForm("client_type", "app")
	if login_token == "" {
		utils.Error(c, -1, "参数错误", nil)
		return
	}
	if client_type != "app" && client_type != "h5" {
		utils.Error(c, -1, "参数错误", nil)
		return
	}
	jg_service := services.GetJguangService()
	mobile, err := jg_service.FastLogin(login_token, client_type)
	if err != nil {
		utils.Error(c, -1, fmt.Sprintf("登录失败：%s", err), nil)
		return
	}
	var _user services.SignRes
	_user, err = services.UserLoginOneStep(mobile, registration_id)
	UserService := services.GetUserService(_user.Uid)
	if err != nil {
		//UserService.AddLoginRecord(login_info.UserAgent, login_info.ModelNumber, login_info.IP, login, "异常", login_info.Bower, fmt.Sprintf("%s", err))
		utils.Error(c, -1, fmt.Sprintf("登录失败：%s", err), nil)
		return
	}
	//UserService.AddLoginRecord(login_info.UserAgent, login_info.ModelNumber, login_info.IP, login, "正常", login_info.Bower, fmt.Sprintf("%s", err))
	UserService.AddUserLog()
	utils.Success(c, "登录成功", _user)
	return
}

type LoginInfo struct {
	IP          string
	UserAgent   string
	ModelNumber string
	Bower       string
}
type Result struct {
	Path string `json:"path"`
}

// getRequestInfo 获取请求信息
func getRequestInfo(c *gin.Context) LoginInfo {
	var info LoginInfo
	var browser, model_number string
	ip := c.ClientIP()
	user_agent := c.Request.Header.Get("User-Agent")
	reg := regexp.MustCompile(`[a-zA-Z]+?/[\d\.]+`)
	bowser_arr := reg.FindAllStringSubmatch(user_agent, -1)
	reg1 := regexp.MustCompile(`\((.+?)\)`)
	system_arr := reg1.FindAllStringSubmatch(user_agent, -1)
	if len(bowser_arr) > 0 && len(bowser_arr[len(bowser_arr)-1]) > 0 {
		browser = bowser_arr[len(bowser_arr)-1][0]
	}
	if len(system_arr) > 0 && len(system_arr[0]) > 1 {
		model_number = system_arr[0][1]
	}
	info.IP = ip
	info.ModelNumber = model_number
	info.Bower = browser
	info.UserAgent = user_agent
	return info
}

// UploadHeaderImg 上传头像
func UploadHeaderImg(c *gin.Context, field string, res_model string, res_id int64, company_id int64, login_user_id int64) (err error) {
	file, _ := c.FormFile(field)
	file_size := file.Size
	name := file.Filename
	mine_type := file.Header.Get("Content-Type")

	key := name + strconv.Itoa(int(time.Now().Unix()))
	file_hash := utils.Md5(key) + "_1920"
	//目标路径
	dir_name := file_hash[0:2]
	dir_path := config.Conf.DataDir + "/filestore/" + config.Conf.Database["postgresql"].DbName + "/" + dir_name
	if _, path_err := os.Stat(dir_path); os.IsNotExist(path_err) {
		os.MkdirAll(dir_path, 0777)
	}
	dst := dir_path + "/" + file_hash

	err = c.SaveUploadedFile(file, dst)
	if err != nil {
		return
	}
	attach_service := services.GetAttachService(0)
	var img image.Image
	img_io, _ := os.Open(dst)
	if img, _, err = image.Decode(img_io); err != nil {
		return
	}
	_, err = attach_service.AddRecord(login_user_id, name, res_model, "image_1920", res_id, company_id, dir_name+"/"+file_hash, file_size, mine_type)
	if err != nil {
		return
	}
	resize_slice := []int{1024, 512, 256, 128}
	for _, size := range resize_slice {
		file_hash = utils.Md5(key) + "_" + strconv.Itoa(size)
		new_dst := dir_path + "/" + file_hash
		field := "image_" + strconv.Itoa(size)
		//缩放保存到1024
		w, h, r_err := attach_service.ResizeImgAndSave(img, new_dst, uint(size))
		if r_err != nil {
			return
		}
		file_size = int64(w * h)
		_, err = attach_service.AddRecord(login_user_id, name, res_model, field, res_id, company_id, dir_name+"/"+file_hash, file_size, mine_type)
		if err != nil {
			return
		}
	}
	return
}

// UploadSimplerImg 简单上传图片
func UploadSimplerImg(c *gin.Context, field string, model string, res_id int64, company_id int64, login_user_id int64) (err error) {
	file, _ := c.FormFile(field)
	file_size := file.Size
	name := file.Filename
	mine_type := file.Header.Get("Content-Type")

	key := name + strconv.Itoa(int(time.Now().Unix()))
	file_hash := utils.Md5(key)
	//目标路径
	dir_name := file_hash[0:2]
	dir_path := config.Conf.DataDir + "/filestore/" + config.Conf.Database["postgresql"].DbName + "/" + dir_name
	if _, path_err := os.Stat(dir_path); os.IsNotExist(path_err) {
		os.MkdirAll(dir_path, 0777)
	}
	dst := dir_path + "/" + file_hash

	err = c.SaveUploadedFile(file, dst)
	if err != nil {
		return
	}
	attach_service := services.GetAttachService(0)
	_, err = attach_service.AddRecord(login_user_id, name, model, field, res_id, company_id, dir_name+"/"+file_hash, file_size, mine_type)
	if err != nil {
		return
	}
	return
}

// uploadAttach 上传附件
func uploadAttach(c *gin.Context, field string, model string, res_id int64, company_id int64, login_user_id int64) (err error) {
	file, _ := c.FormFile(field)
	file_size := file.Size
	name := file.Filename
	mine_type := file.Header.Get("Content-Type")

	key := name + strconv.Itoa(int(time.Now().Unix()))
	file_hash := utils.Md5(key)
	//目标路径
	dir_name := file_hash[0:2]
	dir_path := config.Conf.DataDir + "/filestore/" + config.Conf.Database["postgresql"].DbName + "/" + dir_name
	if _, path_err := os.Stat(dir_path); os.IsNotExist(path_err) {
		os.MkdirAll(dir_path, 0777)
	}
	dst := dir_path + "/" + file_hash

	err = c.SaveUploadedFile(file, dst)
	if err != nil {
		return
	}
	attach_service := services.GetAttachService(0)
	_, err = attach_service.AppendRecord(login_user_id, name, model, "", res_id, company_id, dir_name+"/"+file_hash, file_size, mine_type)
	if err != nil {
		return
	}
	return
}

// PostMobileVerifyCode 发送手机号验证码
func PostMobileVerifyCode(c *gin.Context) {
	mobile := c.PostForm("mobile")
	type_name := c.PostForm("type")
	fmt.Println(type_name)
	match, err := regexp.MatchString(`^1[3456789]\d{9}$`, mobile)
	if err != nil {
		utils.Error(c, -1, "请输入正确的手机号", nil)
		return
	}
	if !match {
		utils.Error(c, -1, "请输入正确的手机号", nil)
		return
	}
	user_id, exist := c.Get("user_id")
	if !exist {
		user_id = int64(0)
	}
	UserService := services.GetUserService(user_id.(int64))
	if type_name == "bind" {
		err = UserService.SendBindVerifyCode(mobile, user_id.(int64))
	} else if type_name == "login" {
		err = UserService.SendLoginVerifyCode(mobile)
	} else if type_name == "register" {
		err = UserService.SendRegisterVerifyCode(mobile)
	} else if type_name == "pass" {
		err = UserService.SendPassVerifyCode(mobile)
	}

	if err != nil {
		utils.Error(c, -1, err.Error(), nil)
		return
	}
	utils.Success(c, "发送成功", nil)
}

// PostMail 发送邮件
func PostMail(c *gin.Context) {
	MailService := services.GetMailService(1)
	err := MailService.SendMail("736025986@qq.com", "哈哈哈")
	if err != nil {
		utils.Error(c, -1, fmt.Sprintf("发送失败：%s", err), nil)
		return
	}
	utils.Success(c, "发送成功", nil)
	return
}

// PostSignup 注册
func PostSignup(c *gin.Context) {
	login := c.DefaultPostForm("login", "")                     //账号
	name := c.DefaultPostForm("company_name", "")               //姓名
	mobile := c.DefaultPostForm("mobile", "")                   //手机号
	email := c.DefaultPostForm("email", "")                     //电子邮件
	password := c.DefaultPostForm("password", "")               //密码
	code := c.DefaultPostForm("code", "")                       //验证码
	registration_id := c.DefaultPostForm("registration_id", "") //极光ID
	if name == "" {
		utils.Error(c, -1, "姓名不能为空", nil)
		return
	}
	if mobile == "" {
		utils.Error(c, -1, "请输入手机号", nil)
		return
	}
	if code == "" {
		utils.Error(c, -1, "请输入验证码", nil)
		return
	}
	//if email == "" {
	//	utils.Error(c, -1, "请输入邮箱", nil)
	//	return
	//}
	if password != "" {
		if !utils.CheckPasswordValid(password) {
			utils.Error(c, -1, "密码长度位8-16，须同时包含字母、数字、符号中的2种", nil)
			return
		}
	} else {
		password = config.Conf.DefaultPassword
	}

	if login == "" {
		login = mobile
	}

	_user, err := services.Signup(login, password, name, email, mobile, code, registration_id)
	if err.Err != nil {
		var errcode int
		if err.Code == 0 {
			errcode = -1
		} else {
			errcode = err.Code
		}
		utils.Error(c, errcode, fmt.Sprintf("注册失败! %s", err.Err), nil)
		return
	}
	//login_info := getRequestInfo(c)
	UserService := services.GetUserService(_user.Uid)
	//UserService.AddLoginRecord(login_info.UserAgent, login_info.ModelNumber, login_info.IP, login, "正常", login_info.Bower, fmt.Sprintf("%s", err.Err))
	UserService.AddUserLog()
	login_type, _ := c.Get("login_type")
	if login_type == "web" {
		session := sessions.Default(c)
		session.Set("user_id", _user.Uid)
		session.Set("user_name", _user.Name)
		session.Set("user_avatar", _user.Image128)
		session.Set("company_id", _user.CompanyId)
		session.Set("access_token", _user.AccessToken)
		err.Err = session.Save()
		if err.Err != nil {
			utils.Error(c, -1, fmt.Sprintf("登录失败：%s", err.Err), nil)
			return
		}
	}
	return
}

// PostForgetPass 忘记密码
func PostForgetPass(c *gin.Context) {
	mobile := c.DefaultPostForm("mobile", "")     //手机号
	password := c.DefaultPostForm("password", "") //密码
	code := c.DefaultPostForm("code", "")         //验证码
	if mobile == "" {
		utils.Error(c, -1, "请输入手机号", nil)
		return
	}
	if code == "" {
		utils.Error(c, -1, "请输入验证码", nil)
		return
	}
	if password == "" {
		utils.Error(c, -1, "请输入密码", nil)
		return
	}
	if !utils.CheckPasswordValid(password) {
		utils.Error(c, -1, "密码长度位8-16，须同时包含字母、数字、符号中的2种", nil)
		return
	}

	err := services.UpdatePasswordByCode(mobile, code, password)
	if err != nil {
		utils.Error(c, -1, fmt.Sprintf("修改失败： %s", err), nil)
		return
	}
	utils.Success(c, "修改成功", nil)
	return
}

// PostBindMobile 绑定手机号
func PostBindMobile(c *gin.Context) {
	mobile := c.PostForm("mobile")
	code := c.PostForm("verify_code")
	user_id, _ := c.Get("user_id")
	match, err := regexp.MatchString(`^1[3456789]\d{9}$`, mobile)
	if err != nil {
		utils.Error(c, -1, "请输入正确的手机号", nil)
		return
	}
	if !match {
		utils.Error(c, -1, "请输入正确的手机号", nil)
		return
	}
	if code == "" {
		utils.Error(c, -1, "请输入验证码", nil)
		return
	}
	UserService := services.GetUserService(user_id.(int64))
	err = UserService.BindLoginMobile(mobile, code)
	if err != nil {
		utils.Error(c, -1, err.Error(), nil)
		return
	}
	utils.Success(c, "修改成功", nil)
}

// GetUserBaseInfo 获取用户基础信息
func GetUserBaseInfo(c *gin.Context) {
	user_id, _ := c.Get("user_id")
	user_service := services.GetUserService(user_id.(int64))
	result, err := user_service.GetUserBaseInfo()
	if err != nil {
		utils.Error(c, -1, fmt.Sprintf("获取失败!：%s", err), nil)
		return
	}
	utils.Success(c, "获取成功", result)
	return
}

// PostUserPassword 修改用户密码
func PostUserPassword(c *gin.Context) {
	oldpwd := c.PostForm("old_password")   //旧密码
	newpwd := c.PostForm("new_password")   //新密码
	repwd := c.PostForm("repeat_password") //新密码
	if newpwd != "" {
		if !utils.CheckPasswordValid(newpwd) {
			utils.Error(c, -1, "密码长度位8-16，须同时包含字母、数字、符号中的2种", nil)
			return
		}
	}
	if repwd != newpwd {
		utils.Error(c, -1, "2次密码不一致", nil)
		return
	}
	user_id, _ := c.Get("user_id")
	user_service := services.GetUserService(user_id.(int64))
	err := user_service.UpdatePassword(oldpwd, newpwd)
	if err != nil {
		utils.Error(c, -1, fmt.Sprintf("更新失败:%s", err), nil)
		return
	}
	utils.Success(c, "修改成功", nil)
	return
}

func PostHelpDeskSubmit(c *gin.Context) {
	name := c.DefaultPostForm("name", "")
	description := c.DefaultPostForm("description", "")
	ticket_type_id_str := c.DefaultPostForm("ticket_type_id", "0")
	email := c.DefaultPostForm("email", "")
	phone := c.DefaultPostForm("phone", "")
	if name == "" || len(name) < 10 {
		utils.Error(c, -1, "标题不能少于10字", nil)
		return
	}
	ticket_type_id, _ := strconv.Atoi(ticket_type_id_str)
	user_id, _ := c.Get("user_id")
	company_id, _ := c.Get("company_id")
	ConsultService := services.GetConsultService()
	ticket_id, err := ConsultService.Create(user_id.(int64), name, description, int64(ticket_type_id), email, phone)
	if err != nil {
		utils.Error(c, -1, err.Error(), nil)
		return
	}
	forms, _ := c.MultipartForm()
	if forms.File != nil {
		for _, file := range forms.File["file"] {
			if file != nil {
				err = uploadAttach(c, "file", "helpdesk.ticket", ticket_id, company_id.(int64), user_id.(int64))
				if err != nil {
					utils.Error(c, -1, fmt.Sprintf("附件上传失败!：%s", err), nil)
					return
				}
			}
		}
	}
	utils.Success(c, "创建成功", ticket_id)
	return
}

type QrUrl struct {
	Url string `json:"url"`
}

// GetLoginQrCode 获取登录二维码
func GetLoginQrCode(c *gin.Context) {
	token := c.DefaultPostForm("token", "")
	if token == "" {
		utils.Error(c, -1, "参数错误", nil)
		return
	}
	url := services.GenerateUserLoginQrCode(token)
	url = "http://" + c.Request.Host + url
	utils.Success(c, "获取成功", QrUrl{url})
	return
}
